package com.stud.common.utils;

import cn.hutool.extra.spring.SpringUtil;
import com.stud.common.annotation.LinkSource;
import com.stud.common.exception.LinkSourceException;
import com.stud.common.jdbc.MyJdbcTemplate;
import com.stud.common.utils.reflect.ReflectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author Stud
 * @date 2023-05-18 09:44:16
 * @description: 快速根据@LinkSource注解翻译对应的值
 */
@Slf4j
public class LinkSourceUtil {
    public static <T> void linkSource(List<T> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        T first = list.get(0);

        List<Field> fields = ReflectUtils.getDeclaredFields(first.getClass());

        List<LinkSource> linkSources = new ArrayList<>();
        List<Field> thisFields = new ArrayList<>();
        Map<String, Field> fieldMap = new HashMap<>();
        for (Field field : fields) {
            fieldMap.put(field.getName(), field);
            LinkSource linkSource = AnnotationUtils.findAnnotation(field, LinkSource.class);

            if (Objects.nonNull(linkSource)) {
                linkSources.add(linkSource);
                thisFields.add(field);
            }
        }

        if (CollectionUtils.isEmpty(linkSources)) {
            return;
        }

        MyJdbcTemplate jdbcTemplate = SpringUtil.getBean(MyJdbcTemplate.class);

        int index = -1;
        for (LinkSource linkSource : linkSources) {
            index++;
            String fieldName = linkSource.field();
            String refTable = linkSource.refTable();
            String refField = linkSource.refField();
            String refWhereField = linkSource.refWhereField();
            boolean multiple = linkSource.multiple();

            if (!fieldMap.containsKey(fieldName)) {
                log.error("解析字段失败:" + fieldName);
            }
            Field field = fieldMap.get(fieldName);

            List<Object> fieldValues = new ArrayList<>();
            for (T entity : list) {
                try {
                    field.setAccessible(true);
                    Object o = field.get(entity);
                    if (Objects.nonNull(o)) {
                        if (multiple) {
                            String[] values = o.toString().split(",");
                            fieldValues.addAll(Arrays.asList(values));
                        } else {
                            fieldValues.add(o);
                        }
                    }
                } catch (IllegalAccessException e) {
                    throw new LinkSourceException("查询关联信息失败");
                }
            }

            if (CollectionUtils.isEmpty(fieldValues)) {
                continue;
            }

            StringBuilder sb = new StringBuilder();
            sb.append("select ").append(refWhereField).append(",").append(refField).append(" from ").append(refTable);
            sb.append(" where ").append(refWhereField).append(" in (").append(Toolkit.Obj2InWithQuotes(fieldValues)).append(")");

            Map linkValueMap = jdbcTemplate.find2Map(sb.toString());
            for (T entity : list) {
                try {
                    Field thisField = thisFields.get(index);
                    thisField.setAccessible(true);
                    if (multiple) {
                        Object o1 = field.get(entity);
                        if (ObjectUtils.isNotEmpty(o1)) {
                            String[] keys = o1.toString().split(",");
                            List values = new ArrayList<>();
                            for (String key : keys) {
                                values.add(linkValueMap.get(key));
                            }
                            thisField.set(entity, StringUtils.join(values, ","));
                        }
                    } else {
                        thisField.set(entity, linkValueMap.get(field.get(entity)));
                    }
                } catch (IllegalAccessException e) {
                    throw new LinkSourceException("插入关联信息失败");
                }
            }
        }

    }

    public static <T> void linkSource(T entity) {
        if (Objects.isNull(entity)) {
            return;
        }
        linkSource(Arrays.asList(entity));
    }
}
